package org.zjx.task;

import lombok.Getter;
import lombok.Setter;
import org.zjx.task.core.ITask;
import org.zjx.task.core.ITaskChain;
import org.zjx.task.core.TaskScheduler;
import org.zjx.task.exception.ChainExecutionException;
import org.zjx.task.exception.RestartChainException;
import org.zjx.task.exception.TaskExecutionException;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 抽象任务链基础实现（线程安全）
 */
@Getter
@Setter
public abstract class AbstractChain implements ITaskChain {
    //----------- 核心状态字段 -----------//
    protected final String chainId;
    protected List<ITask> tasks = new ArrayList<>();
    protected final AtomicInteger currentPosition = new AtomicInteger(0);
    protected final Map<String, Object> params = new ConcurrentHashMap<>();
    protected final AtomicInteger restartCount = new AtomicInteger(0);
    protected volatile int maxRestart = 3;

    //----------- 暂停控制相关 -----------//
    private final Object pauseLock = new Object();
    protected final AtomicBoolean paused = new AtomicBoolean(false);

    public AbstractChain(String chainId) {
        this.chainId = Objects.requireNonNull(chainId, "Chain ID cannot be null");
    }

    //----------- 接口方法实现 -----------//
    @Override
    public String getChainId() {
        return chainId;
    }

    @Override
    public List<ITask> getTasks() {
        return tasks;
    }

    @Override
    public void addTask(ITask task) {
        tasks.add(task);
    }

    @Override
    public void addTask(List<ITask> tasks) {
        if (tasks == null || tasks.isEmpty()) return;
        this.tasks.addAll(tasks);
    }

    @Override
    public int currentTaskIndex() {
        return currentPosition.get();
    }

    public void setCurrentTaskIndex(int index) {
        currentPosition.set(index);
    }

    @Override
    public Map<String, Object> getParams() {
        return params;
    }

    @Override
    public void setParams(Map<String, Object> params) {
        if (params != null) this.params.putAll(params);
    }

    @Override
    public void pause() {
        synchronized (pauseLock) {
            paused.set(true);
        }
    }

    @Override
    public void resume() {
        synchronized (pauseLock) {
            paused.set(false);
            pauseLock.notifyAll();
        }
    }

    @Override
    public boolean isPaused() {
        return paused.get();
    }

    @Override
    public int getRestartCount() {
        return restartCount.get();
    }

    //----------- 核心执行逻辑 -----------//
    @Override
    public void execute(TaskScheduler scheduler) throws ChainExecutionException {
        // 每次执行创建新的上下文
        ChainContext context = new ChainContext();
        context.setCurrentChain(this);
        context.setParams(params);

        try {
            while (currentPosition.get() < tasks.size() && !context.isChainInterrupted()) {
                checkPauseState(); // 检查暂停状态
                ITask task = tasks.get(currentPosition.get());
                context.setCurrentChainIndex(currentPosition.get());
                try {
                    scheduler.executeTask(task, context);
                    currentPosition.incrementAndGet(); // 只有成功执行才前进
                } catch (TaskExecutionException e) {
                    handleTaskFailure(task, context, e);
                }
            }
            scheduler.waitAllAsyncTasks();
        } catch (RestartChainException e) {
            handleChainRestart(e); // 处理链重启
        } catch (InterruptedException e) {
            handleInterruption(context); // 处理线程中断
        } finally {
            resetChainState(); // 重置链状态
        }
    }

    /**
     * 处理任务失败逻辑
     * @param task 失败的任务
     * @param context 执行上下文
     * @param e 任务异常
     */
    private void handleTaskFailure(ITask task, ChainContext context, TaskExecutionException e)
            throws ChainExecutionException {
        switch (task.getFailureStrategy()) {
            case STOP:
                handleStopStrategy(task, context, e);
                break;
            case RESTART:
                throw new RestartChainException(chainId);
            case CONTINUE:
                currentPosition.incrementAndGet();
                break;
            case FALLBACK:
                handleFallbackStrategy();
                break;
            default:
                throw new ChainExecutionException("Unknown failure strategy", chainId, currentPosition.get());
        }
    }

    /**
     * 处理STOP策略：达到重试次数后停止链
     */
    private void handleStopStrategy(ITask task, ChainContext context, TaskExecutionException e)
            throws ChainExecutionException {
        if (task instanceof RetryTask) {
            RetryTask retryTask = (RetryTask) task;
            if (retryTask.getRetryCount() < retryTask.getMaxRetries()) {
                retryTask.resetForRetry();
                return;
            }
        }
        context.setChainInterrupted(true);
        throw new ChainExecutionException(e.getMessage(), chainId, currentPosition.get());
    }


    /**
     * 处理FALLBACK策略：回退到上一个任务
     */
    private void handleFallbackStrategy(){
        int newPosition = Math.max(0, currentPosition.get() - 1);
        currentPosition.set(newPosition);
        tasks.get(currentPosition.get()).initialize();
    }

    /**
     * 处理链重启
     */
    private void handleChainRestart(RestartChainException e) throws ChainExecutionException {
        if (restartCount.get() < maxRestart) {
            resetChainForRestart();
            throw e; // 重新抛出让调度器处理重新入队
        }
        throw new ChainExecutionException("Max restart attempts exceeded", chainId, currentPosition.get());
    }

    /**
     * 处理线程中断
     */
    private void handleInterruption(ChainContext context) throws ChainExecutionException {
        Thread.currentThread().interrupt();
        context.setChainInterrupted(true);
        throw new ChainExecutionException("Chain interrupted", chainId, currentPosition.get());
    }

    /**
     * 重置链状态以便重启
     */
    private void resetChainForRestart() {
        restartCount.incrementAndGet();
        System.out.println(chainId + " restart count: " + restartCount.get());
        currentPosition.set(0);
        tasks.forEach(ITask::initialize);
    }

    /**
     * 执行结束后的状态重置
     */
    private void resetChainState() {
        paused.set(false);
        currentPosition.set(0);
        tasks.forEach(ITask::initialize);
//        params.clear();
    }

    /**
     * 检查暂停状态（阻塞直到恢复）
     */
    private void checkPauseState() throws InterruptedException {
        synchronized (pauseLock) {
            while (paused.get()) {
                pauseLock.wait();
            }
        }
    }
}